package com.white.commonlib.engine;

import android.os.SystemClock;

import java.util.Timer;
import java.util.TimerTask;

/**
 * Created by yutf on 2017/6/12 0012.<br/>
 * <p>
 * 计时器
 * 0  时钟模式，一般用于时钟00:00  1  快速计时模式，用于定时刷新任务
 */

public class CalcTimer
{

    private Timer mTimer;
    private CalcTask mTask;

    private long hour, min, second;
    private long threshold;
    private OnTimeElapseListener ll;

    /**
     * 触发间隔
     */
    private int delay;

    public static final int TYPE_TIMER = 0;
    public static final int TYPE_REFRESH = 1;
    /**
     * 计时类型  0  时钟模式，一般用于时钟00:00  1  快速计时模式，用于定时刷新任务
     */
    private int calcType;

    private final int STATE_RUNNING = 1;
    private final int STATE_PAUSE = 2;
    private final int STATE_DESTROY = 3;
    private final int STATE_INIT = 0;
    /***计时器状态*/
    private volatile int state = STATE_INIT;

    /****
     * 给定时间间隔构造一个时钟计时器
     * @param delay 毫秒
     */
    public CalcTimer(int delay)
    {
        this(delay, TYPE_TIMER);
    }

    /***
     * 给定时间间隔构造一个定时刷新器
     * @param delay
     * @param type 0 计时  1 定时刷新
     */
    public CalcTimer(int delay, int type)
    {
        this.delay = delay;
        this.calcType = type;
        reset();
    }

    /***
     * 设置阈值，到达阈值自动置0
     * @param threshold
     */
    public void setThreshold(long threshold)
    {
        this.threshold = threshold;
        if(threshold == Long.MAX_VALUE)
            throw new RuntimeException("threshold too large");
    }

    public void reset()
    {
        releaseTimer();
        //状态复原
        state = STATE_INIT;
        mTimer = new Timer();
        mTask = new CalcTask();
        hour = 0;
        min = 0;
        second = 0;
    }

    public void destroy()
    {
        releaseTimer();
        state = STATE_DESTROY;
    }

    private void releaseTimer()
    {
        if (mTask != null)
        {
            mTask.cancel();
            mTask = null;
        }
        if (mTimer != null)
        {
            mTimer.cancel();
            mTimer = null;
        }
        state = STATE_INIT;
    }

    public void start(OnTimeElapseListener l)
    {
        if (state != STATE_RUNNING)
        {
            state = STATE_RUNNING;
            this.ll = l;
            mTimer.scheduleAtFixedRate(mTask, 0, delay);
        }
    }

    public void pause()
    {
        if (state != STATE_PAUSE)
        {
            state = STATE_PAUSE;
            //如果没有开始则不响应
            if (mTask != null)
            {
                mTask.cancel();
                mTask = null;
            }
            if (ll != null)
            {
                ll.onPause();
            }
        }
    }

    public void resume()
    {
        if (state == STATE_PAUSE)
        {
            state = STATE_RUNNING;
            //如果没有开始则不响应
            //如果正在运行则不响应
            mTask = new CalcTask();
            mTimer.scheduleAtFixedRate(mTask, delay, delay);
            if (ll != null)
            {
                ll.onResume();
            }
        }
    }

    public interface OnTimeElapseListener
    {
        /***
         * 计时模式会返回时间，
         * @param hour    0
         * @param minuet  0
         * @param seconds 刷新次数
         */
        void onChanged(long hour, long minuet, long seconds);

        void onPause();

        void onResume();
    }

    public static abstract class SimpleElapseListener implements OnTimeElapseListener
    {
        public void onPause(){}

        public void onResume(){}
    }

    private class CalcTask extends TimerTask
    {
        @Override
        public void run()
        {
            while (state == STATE_PAUSE)
            {
                SystemClock.sleep(50);
            }
            if (state == STATE_DESTROY)
                return;

            if (ll != null)
            {
                ll.onChanged(hour, min, second);
            }
            if (calcType == 0)
            {
                timeCalc();
            }else
            {
                second++;
                if(second > threshold)
                {
                    second = 1;
                }
            }
        }

        private void timeCalc()
        {
            second++;
            if (second >= 60)
            {
                second = 0;
                min++;
                if (min >= 60)
                {
                    min = 0;
                    hour++;
                }
            }
        }
    }
}
